package com.meronmee.common.core.util;


import com.github.benmanes.caffeine.cache.CacheLoader;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

/**
 * Caffeine 本地内存缓存工具
 * @author Meron
 */
public enum LocalCache {
    /** 1分钟缓存 */
	MIN1(60),
    /** 3分钟缓存 */
    MIN3(180),
    /** 5分钟缓存 */
    MIN5(300),
    /** 30分钟缓存 */
    MIN30(1800);

	/** 缓存有效时长，单位:秒*/
    private int duration;
    /**
     * Caffeine缓存
     */
    private LoadingCache<String, Object> cache;

    private Logger log = LoggerFactory.getLogger(LocalCache.class);
    private static final int init = 1;  //缓存容量初始大小
    private static final int max = 1000;  //缓存实体的最大数目

    //构造函数（枚举类型的构造函数只能为私有类型）
    private LocalCache(int duration) {
        log.info("Initializing local cache..." + this.name());
        cache = Caffeine.newBuilder()
                .initialCapacity(init)
                .maximumSize(max)
                .expireAfterWrite(duration, TimeUnit.SECONDS)
                .build(new CacheLoader<String, Object>() {
                    //默认的数据加载实现，当调用get取值的时候，如果key没有对应的值，就调用这个方法进行加载
                    @Override
                    public Object load(String key) throws Exception {
                        return null;
                    }
                });
    }
    
    /**
     * 获取缓存
     * @param key
     * @return
     */
    public Object get(String key){
    	if(key==null || key.length()==0){
    		return null;
    	}
    	return cache.getIfPresent(key);
    }

    /**
     * 获取缓存， "if cached, return; otherwise create, cache and return"<p>
     * @param key
     * @param function 获取不到缓存的时候function的返回值将被缓存，并返回
     * @return
     */
    public Object get(String key, Function<String, ?> function){
        if(key==null || key.length()==0){
            return null;
        }

        //示例：
        /*
        cache.get(key, k -> {
            //如果获取不到，则缓存该值并返回
            return "";
        });
        或
        cache.get(key, new Function<String, Object>() {
            /**
             * 如果获取不到，则缓存该值并返回
             * @param key 同外层的key
             * @return 如果获取不到，则缓存该值并返回
             *  /
            @Override
            public Object apply(String key) {
                return 2;
            }
        });
        */
        return cache.get(key, function);
    }
    
    /**
     * 批量获取缓存
     * @param keys
     * @return 返回不可更改的map
     */
    @SuppressWarnings("unchecked")
	public Map<String, Object> getBatch(String... keys){
    	if(keys==null || keys.length==0){
    		return Collections.EMPTY_MAP;
    	}
    	return cache.getAllPresent(Arrays.asList(keys));
    }
    
    /**
     * 设置缓存
     * @param key
     * @param value
     */
    public void set(String key, Object value){
    	if(key==null || key.length()==0||value==null){
    		return;
    	}
        cache.put(key, value);
    }
    /**
     * 删除缓存
     * @param key
     */
    public void delete(String key){
    	if(key==null){
    		return;
    	}
        cache.invalidate(key);
    }
}
